package com.breeze.blockchain.socket;

import static com.breeze.components.core.exception.error.ErrorCode.INTERNAL_SERVER_ERROR;

import com.breeze.components.socket.BaseWebSocketHandler;
import java.util.Objects;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

/**
 * WebSocket处理器
 *
 * @author breeze
 */
@Component
@Slf4j
public class WebSocketController extends BaseWebSocketHandler {

  private WebSocketSession session;

  /** 连接打开 */
  @Override
  public void afterConnectionEstablished(@NonNull WebSocketSession session) {
    connect(getSessionId(session), session);
    this.session = session;
    log.info("[websocket] 新的连接：id={}", getSessionId(session));
  }

  /** 接收到消息 */
  @Override
  protected void handleTextMessage(
      @NonNull WebSocketSession session, @NonNull TextMessage message) {
    log.info("接收到消息：{}", message.getPayload());
    receiveMessage(getSessionId(session), message.getPayload());
  }

  /** 连接关闭 */
  @Override
  public void afterConnectionClosed(
      @NonNull WebSocketSession session, @NonNull CloseStatus status) {
    String sessionId = getSessionId(session);
    disconnect(sessionId);
    log.info("[websocket] 连接断开：id={}，reason={}", sessionId, status);
  }

  /** 连接错误退出 */
  @Override
  public void handleTransportError(@NonNull WebSocketSession session, @NonNull Throwable throwable)
      throws Exception {
    if (Objects.isNull(this.session)) {
      return;
    }
    String sessionId = getSessionId(session);
    log.info("[websocket] 连接异常：id={}，throwable={}", sessionId, throwable.getMessage());
    this.session.close(CloseStatus.SERVER_ERROR);
    disconnect(sessionId);
  }

  private String getSessionId(WebSocketSession session) {
    String sessionId = (String) session.getAttributes().get("sessionId");
    INTERNAL_SERVER_ERROR.notEmpty(sessionId);
    return sessionId;
  }
}
